package com.sanq.product.books.controller;

import com.sanq.product.books.config.Redis;
import com.sanq.product.books.entity.vo.BooksShelfVo;
import com.sanq.product.books.entity.vo.BooksVo;
import com.sanq.product.books.entity.vo.CollectionVo;
import com.sanq.product.books.entity.vo.UsersVo;
import com.sanq.product.books.es.module.vo.BooksSearchVo;
import com.sanq.product.books.es.service.BooksSearchService;
import com.sanq.product.books.service.BooksService;
import com.sanq.product.books.service.BooksShelfService;
import com.sanq.product.books.service.ChapterService;
import com.sanq.product.books.service.CollectionService;
import com.sanq.product.books.utils.WebUtil;
import com.sanq.product.config.utils.annotation.LogAnnotation;
import com.sanq.product.config.utils.entity.Response;
import com.sanq.product.config.utils.futures.Future;
import com.sanq.product.config.utils.string.StringUtil;
import com.sanq.product.config.utils.web.JsonUtil;
import com.sanq.product.redis.service.JedisPoolService;
import com.sanq.product.security.annotation.IgnoreSecurity;
import com.sanq.product.utils.es.entity.SearchPager;
import com.sanq.product.utils.es.entity.SearchPagination;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.List;
import java.util.Map;

@RestController
@RequestMapping("/app/books")
public class BooksController {

    @Resource
    private BooksService booksService;
    @Resource
    private JedisPoolService jedisPoolService;
    @Resource
    private CollectionService collectionService;
    @Resource
    private BooksShelfService booksShelfService;
    @Resource
    private ChapterService chapterService;
    @Resource
    private ThreadPoolTaskExecutor taskExecutor;
    @Resource
    private BooksSearchService booksSearchService;

    public static final String IS_COLLECTION = "isCollection";
    public static final String IS_ADD_SHELF = "isAddShelf";

    @IgnoreSecurity
    @LogAnnotation(description = "通过ID得到详情")
    @GetMapping(value = "/get/{id}")
    public Response getById(HttpServletRequest request, @PathVariable("id") Long id) {
        BooksVo booksVo = booksService.findById(id);

        String token = WebUtil.getToken(request);

        UsersVo usersVo = null;
        if (StringUtil.isEmpty(token)) {
            booksVo.setCollection(false);
            booksVo.setAddToShelf(false);
        } else {
            usersVo = JsonUtil.json2Obj(jedisPoolService.get(Redis.ReplaceKey.getTokenUser(token)), UsersVo.class);

            final Integer userId = usersVo != null ? usersVo.getId() : 0;
            Map<String, Object> map = new Future.Builder()
                    .setExecutor(taskExecutor)
                    .option(IS_COLLECTION, () -> {
                        CollectionVo params = new CollectionVo();
                        params.setBookId(id);
                        params.setUserId(userId);
                        return collectionService.findCount(params) != 0;
                    })
                    .option(IS_ADD_SHELF, () -> {
                        BooksShelfVo booksShelfVo = new BooksShelfVo();
                        booksShelfVo.setBookId(id);
                        booksShelfVo.setUserId(userId);
                        return booksShelfService.findCount(booksShelfVo) != 0;
                    })
                    .build().run();

            booksVo.setCollection((Boolean) map.get(IS_COLLECTION));
            booksVo.setAddToShelf((Boolean) map.get(IS_ADD_SHELF));
        }

        Long chapterId = chapterService.findChapterByBookId(id, usersVo);
        booksVo.setChapterId(chapterId == null ? chapterService.findChapterByBookId(id, null) : chapterId);

        return booksVo != null ? new Response().success(booksVo) : new Response().failure();
    }

    @IgnoreSecurity
    @LogAnnotation(description = "小说列表")
    @GetMapping(value = "/list")
    public Response findListByPager(HttpServletRequest request,
                                    BooksSearchVo booksSearchVo,
                                    SearchPagination searchPagination) {

        if (StringUtil.isEmpty(booksSearchVo.getIsOver()))
            booksSearchVo.setIsOver(null);

        if (StringUtil.isEmpty(booksSearchVo.getChildSortId()))
            booksSearchVo.setChildSortId(null);

        SearchPager<BooksSearchVo> searchPager = booksSearchService.findBooksListByPager(booksSearchVo, searchPagination);

        searchPager = getData(searchPager);

        if (searchPager == null)
            return new Response().failure();

        return new Response().success(searchPager);
    }

    @IgnoreSecurity
    @LogAnnotation(description = "根据用户定制的兴趣分类来查询小说")
    @GetMapping(value = "/findListBySortIds")
    public Response findListBySortIds(HttpServletRequest request, BooksSearchVo booksSearchVo, SearchPagination pagination) {
        String token = WebUtil.getToken(request);

        SearchPager<BooksSearchVo> pager;
        if (StringUtil.isEmpty(token))
            pager = booksSearchService.findBooksListByPager(booksSearchVo, pagination);
        else {
            List<String> sortIdList = jedisPoolService.getList(Redis.ReplaceKey.getTokenJoinSort(token), 0L, -1L);

            if (sortIdList != null && !sortIdList.isEmpty()) {
                StringBuffer sb = new StringBuffer();
                sortIdList.stream().forEach(sortId -> {
                    sb.append(sortId).append(",");
                });

                booksSearchVo.setChildSortId(sb.deleteCharAt(sb.length() - 1).toString());
            }

            pager = booksSearchService.findBooksListByPager(booksSearchVo, pagination);
        }
        pager = getData(pager);

        if (pager == null)
            return new Response().failure();

        return new Response().success(pager);
    }

    private SearchPager<BooksSearchVo> getData(SearchPager<BooksSearchVo> pager) {
        if (pager == null)
            return pager;

        List<BooksSearchVo> data = pager.getData();
        if (data != null && !data.isEmpty()) {
            BooksSearchVo vo;
            for (BooksSearchVo datum : data) {
                vo = datum;
                vo.setBooksVo(booksService.findById(vo.getId()));
            }
        }
        return pager;
    }
}